﻿using System;
using biz.ritter.javapi.io;
using biz.ritter.javapi.lang;
using biz.ritter.javapi.util;
using Nofs.Net.Fuse.Impl;

namespace Nofs.Net.Execution
{
    public class ExternalToInternalPathTranslator
    {
        private static String _mountPath;
        private static String _separatorChar = "" + File.separatorChar;

        public static void SetMountPath(String path)
        {
            _mountPath = path;
            StringBuffer txt = new StringBuffer();
            txt.append("mount path set as: ");
            txt.append(_mountPath);
            Console.WriteLine(txt);
        }

        public static String Translate(String path)// throws Exception 
        {
            return Translate(_mountPath, TranslateRelativePath(_mountPath, path));
        }

        public static String Translate(String pwd, String path) //throws Exception 
        {
            StringBuffer txt = new StringBuffer("Translate(pwd = ");
            txt.append(pwd);
            txt.append(", path = ");
            txt.append(path);
            txt.append(")");
            new LogManager().LogInfo(txt.toString());
            String translatedPath;
            if (path.startsWith(_separatorChar))
            {
                translatedPath = TranslateAbsPath(TranslateToNoDots(path));
            }
            else
            {
                String newPwd = TranslateToNoDots(pwd);
                String relativeTranslated = TranslateRelativePath(newPwd, path);
                String relativeNoDots = TranslateToNoDots(relativeTranslated);
                translatedPath = TranslateAbsPath(relativeNoDots);
            }
            return translatedPath.compareTo("") == 0 ? _separatorChar : translatedPath;
        }

        private static String JoinPath(LinkedList<String> parts)
        {
            StringBuffer builder = new StringBuffer();
            foreach (String part in parts)
            {
                builder.append(File.separatorChar);
                builder.append(part);
            }
            return builder.toString();
        }

        private static String TranslateRelativePath(String pwd, String path) //throws Exception 
        {
            if (!pwd.EndsWith(_separatorChar) && !path.startsWith(_separatorChar))
            {
                StringBuffer txt = new StringBuffer();
                txt.append(pwd);
                txt.append(_separatorChar);
                txt.append(path);
                return txt.toString();
            }
            StringBuffer text = new StringBuffer();
            text.append(pwd);
            text.append(path);
            return text.toString();
        }

        private static String TranslateAbsPath(String path) //throws Exception 
        {
            if (!path.startsWith(_mountPath))
            {
                StringBuffer txt = new StringBuffer();
                txt.append("'");
                txt.append(path);
                txt.append("' not in mounted fs path: '");
                txt.append(_mountPath);
                txt.append("'");
                throw new System.Exception(txt.toString());
            }
            int startIndex = _mountPath.length();
            int endIndex = startIndex + (path.length() - _mountPath.length());
            return path.substring(startIndex, endIndex);
        }

        private static String TranslateToNoDots(String path) //throws Exception 
        {
            if (path.Contains(".") || path.Contains(".."))
            {
                LinkedList<String> parts = new LinkedList<String>();
                foreach (String pathPart in PathUtil.SplitPath(path))
                {
                    if (pathPart.compareTo(".") == 0)
                    {
                    }
                    else if (pathPart.compareTo("..") == 0)
                    {
                        parts.removeLast();
                    }
                    else
                    {
                        parts.add(pathPart);
                    }
                }
                return JoinPath(parts);
            }
            else
            {
                return path;
            }
        }
    }

}
